package view.helper;

import java.lang.reflect.Method;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zul.Image;
import org.zkoss.zul.Div;

import view.component.CardComponent;

abstract public class CardHolder extends Div {
	
	private Image img;
	
	protected Adaptor adaptor;
	protected String imgPath;
		
	protected Integer zindex = 0;
	protected CardHolder topHolder = null;
	protected CardComponent lastCard = null; 
		
		
	public CardHolder() {
		this("image/FreeCell.png");				
	}
	
	public CardHolder(String imgPath) {
		img =  new Image(imgPath);		
		img.setParent(this); 
		setStyle("position:absolute;");
		this.imgPath = imgPath;		
		setDroppable("true"); 
		//addForward("onDrop", getParent(), "onCardDrop");
	}
	
	public void pushCard(CardComponent card)	{ 		
		if (lastCard==null) {
			cleanOldParent(card);
			initNewParent(card);
			autoAdaptCardDepth(card);
			topHolder.applyRules(card);						
		} else {
			lastCard.pushCard(card);
		}
	}
	
	public void popTail() {
		lastCard = null;
	}
	
	private void cleanOldParent(CardComponent card) {
		if (card.getParent()!=null) {
			((CardHolder)card.getParent()).popTail();
		}
	}
	
	private void initNewParent(CardComponent card) {
		card.setParent(this);
		card.setZindex(zindex+10);			
		card.setTopHolder(topHolder);		
		lastCard = card;
	}
	
	private void autoAdaptCardDepth(CardComponent card) {
		String cardDepth = card.getTop();
		if (cardDepth!=null) {
			String holderDepth = topHolder.getStep(card).toString() + "px";
			//System.out.println(cardDepth+" -- "+holderDepth);
			if (!cardDepth.equals(holderDepth)) {
				//System.out.println("Redrawing()");
				card.draw();
			}
		}
	}
	
	public void applyRules(CardComponent card) {
		//to apply later
	}
	
	public CardHolder getTopHolder() {
		return topHolder;
	}
	
	public void setTopHolder(CardHolder topHolder) {
		this.topHolder = topHolder;
	}
	
	public void setAdaptor(Adaptor adaptor) {
		this.adaptor = adaptor;
	}	
	
	public void drawAtPosition(Integer top, Integer left) {					
		setTop(top.toString()+"px");	
		setLeft(left.toString()+"px");
		
	}
	
	public Integer getStep(CardComponent card) {
		return topHolder.getStep(card);
	}
	
	public CardComponent getLastCard() {
		return lastCard;
	}
	
	public void onDrop(DropEvent evt) {
		CardComponent dragged = (CardComponent) evt.getDragged();
		updateAdaptor(dragged, topHolder);	      
	}
	
	protected void updateAdaptor(CardComponent dragged, CardHolder topHolder) {
		String sourceComponentSimpleClassName = dragged.getTopHolder().getClass().getSimpleName();
		String targetComponentSimpleClassName = topHolder.getClass().getSimpleName();
		String adaptorMoveMethod = "on" + 
			targetComponentSimpleClassName + "DropFrom" + sourceComponentSimpleClassName;
		
		try {
			Class thisClass = adaptor.getClass();
			Class[] params = {dragged.getClass(), topHolder.getClass()};
			Method doMethod = thisClass.getMethod(adaptorMoveMethod, params);
			//System.out.println(doMethod);			
			doMethod.invoke(adaptor, dragged, topHolder);		
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public String toString() {
		return imgPath;
	}
	

	
	
}
